package com.shensi.appCollect.pay.strategy;

import cn.hutool.core.lang.UUID;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.shensi.appCollect.param.request.SxfQueryTerminalReq;
import com.shensi.appCollect.pay.PayChannel;
import com.shensi.appCollect.pay.PaymentStrategy;
import com.shensi.appCollect.pay.QueryOrderStrategy;
import com.shensi.appCollect.pay.strategy.order.SXFQueryOrder;
import com.shensi.appCollect.pay.strategy.payment.SXFPayment;
import com.shensi.appCollect.pojo.dto.SxfQueryTerminalListDTO;
import com.shensi.appCollect.utils.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.annotation.PostConstruct;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Iterator;
import java.util.Map;

/**
 * @date 2023/8/11
 */
@Component
public class SXFChannel implements PayChannel {

    private static final Logger log = LoggerFactory.getLogger(SXFChannel.class);

    public static final String BIZ_CODE_SUCCESS = "0000";

    @Autowired
    private SXFPayment sxfPayment;
    @Autowired
    private SXFQueryOrder sxfQueryOrder;
    @Autowired
    private RestTemplate restTemplate;
    private DateTimeFormatter timestampFormatter;
    @Value("92346959")
    private String orgId;
//    @Value("${tianque.tradeReversePayPrivatekey}")
    private String privateKey;
    private String baseUrl;

    @PostConstruct
    public void postCons(){
        timestampFormatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
        privateKey = SXFPaySign.privateKey;
        baseUrl = "https://openapi.tianquetech.com";
    }

    @Override
    public void init() {

    }

    @Override
    public PaymentStrategy getPayStrategy() {
        return sxfPayment;
    }

    @Override
    public QueryOrderStrategy getQueryOrderStrategy() {
        return sxfQueryOrder;
    }

    public SxfQueryTerminalListDTO queryThirdPartyTerminal(SxfQueryTerminalReq req){
        ApiResponseBean<SxfQueryTerminalListDTO> post = this.doPost(baseUrl + "/merchant/merchantTerminal/queryThirdPartyTerminal", req,SxfQueryTerminalListDTO.class);
        return post == null ? null : post.getRespData();
    }

    public <T> ApiResponseBean<T> doPost(String url, Object req,Class<T> resClass){
        ApiRequestBean<Object> requestBean = new ApiRequestBean<>();
        requestBean.setOrgId(orgId);
        requestBean.setReqId(UUID.fastUUID().toString(true));
        requestBean.setVersion("1.0");
        requestBean.setSignType("RSA");
        requestBean.setTimestamp(timestampFormatter.format(LocalDateTime.now()));
        requestBean.setReqData(req);
        return doPost(url,requestBean,resClass);
    }

    public <T> ApiResponseBean<T> doPost(String url,ApiRequestBean<?> requestBean,Class<T> resClass){
        try {
            requestBean.setSign(null);
            requestBean.setSign(signData(requestBean));
            String reqStr = JsonUtils.objectToJson(requestBean);
            log.info("随行付请求,url:[{}],body:[{}]",url,reqStr);
            ResponseEntity<String> response = restTemplate.postForEntity(url, requestBean, String.class, (Object) null);
            if (response.getBody() == null) {
                return null;
            }
            log.info("随行付返回,res:[{}]",response.getBody());
            JavaType javaType = JsonUtils.DEFAULT_JSON_MAPPER.getTypeFactory().constructParametricType(ApiResponseBean.class, resClass);
            return JsonUtils.DEFAULT_JSON_MAPPER.readValue(response.getBody(),javaType);
        } catch (Exception e) {
            log.error("随行付请求失败", e);
        }
        return null;
    }

    private String signData(ApiRequestBean<?> req) throws Exception {
        JsonNode jsonNode = JsonUtils.DEFAULT_JSON_MAPPER.valueToTree(req);
        StringBuilder sb = new StringBuilder();
        Iterator<Map.Entry<String, JsonNode>> fields = jsonNode.fields();
        int i = 0;
        while (fields.hasNext()) {
            Map.Entry<String, JsonNode> next = fields.next();
            String key = next.getKey();
            JsonNode value = next.getValue();
            if (value.isNull()) {
                continue;
            }
            i++;
            if (i != 1) {
                sb.append("&");
            }
            sb.append(key).append("=");
            if (value.isArray() || value.isObject()) {
                sb.append(value);
            }else{
                sb.append(value.asText());
            }
        }
        return RSASignature.encryptBASE64(RSASignature.sign(sb.toString(), this.privateKey));
    }

}
